#include "VSPostEffectSet.h"
#include "VSPEBeginFunction.h"
#include "VSPEEndFunction.h"
#include "VSGraphicInclude.h"
#include "VSPEGray.h"
#include "VSRenderTarget.h"
#include "VSStream.h"
using namespace VSEngine2;
VSPointer<VSPostEffectSet> VSPostEffectSet::Default = NULL;
bool VSPostEffectSet::ms_bIsEnableASYNLoader = false;
bool VSPostEffectSet::ms_bIsEnableGC = true;
IMPLEMENT_RTTI(VSPostEffectSet,VSObject)
BEGIN_ADD_PROPERTY(VSPostEffectSet,VSObject)
REGISTER_PROPERTY(m_ResourceName,ResourceName,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_PROPERTY(m_pPEBeginFunc,BeginFuntion,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_PROPERTY(m_pPEEndFunc,EndFunction,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_PROPERTY(m_pPostEffectFunctionArray,PostEffectFunctionArray,VSProperty::F_SAVE_LOAD_CLONE)
END_ADD_PROPERTY
IMPLEMENT_INITIAL_BEGIN(VSPostEffectSet)
IMPLEMENT_INITIAL_END
VSPostEffectSet::VSPostEffectSet()
{
	m_pPostEffectFunctionArray.Clear();

	m_pPEBeginFunc = VS_NEW VSPEBeginFunction(_T("Begin"),this);
	m_pPEEndFunc = VS_NEW VSPEEndFunction(_T("End"),this);
}
VSPostEffectSet::~VSPostEffectSet()
{
	for (unsigned int i = 0 ; i < m_pPostEffectFunctionArray.GetNum() ; i++)
	{
		VSPostEffectFunction * pShaderFunction = m_pPostEffectFunctionArray[i];
		m_pPostEffectFunctionArray[i] = NULL;
		VSMAC_DELETE(pShaderFunction);
	}
	m_pPostEffectFunctionArray.Clear();

	m_pPEBeginFunc = NULL;
	m_pPEEndFunc = NULL;
}
void VSPostEffectSet::AddPostEffectFunction(VSPostEffectFunction * pPostEffectFunction)
{
	if(pPostEffectFunction)
	{
		m_pPostEffectFunctionArray.AddElement(pPostEffectFunction);
	}

}
void VSPostEffectSet::DeletePostEffectFunction(VSPostEffectFunction * pPostEffectFunction)
{
	if(pPostEffectFunction)
	{
		for (unsigned int i = 0 ; i < m_pPostEffectFunctionArray.GetNum() ; i++)
		{
			if(m_pPostEffectFunctionArray[i] == pPostEffectFunction)
			{
				m_pPostEffectFunctionArray.Erase(i);
				return ;
			}
		}

	}

}
unsigned int VSPostEffectSet::DiskUse()const
{
	unsigned int Used = VSObject::DiskUse();

	Used += VSResource::DiskUse();

	Used += sizeof(VSPEBeginFunction *);
	Used += sizeof(VSPEEndFunction *);
	Used += sizeof(unsigned int);
	Used += sizeof(VSPostEffectFunction *) * m_pPostEffectFunctionArray.GetNum();


	return Used;
}

bool VSPostEffectSet::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSObject::Save(rStream,iSaveUse))
		return 0;

	if (!VSResource::Save(rStream,iSaveUse))
	{
		return 0;
	}


	if(!rStream.WriteObjectPtr(m_pPEBeginFunc))
		return 0;
	iSaveUse +=sizeof(VSPostEffectFunction *);

	if(!rStream.WriteObjectPtr(m_pPEEndFunc))
		return 0;
	iSaveUse +=sizeof(VSPostEffectFunction *);

	unsigned int uiPostFunctionNum = m_pPostEffectFunctionArray.GetNum();
	if(!rStream.Write(&uiPostFunctionNum,sizeof(unsigned int)))
		return 0;
	iSaveUse +=sizeof(unsigned int);

	for (unsigned int i = 0 ; i < uiPostFunctionNum ; i++)
	{

		if(!rStream.WriteObjectPtr(m_pPostEffectFunctionArray[i]))
			return 0;
		iSaveUse +=sizeof(VSPostEffectFunction *);
	}

	return 1;
}
bool VSPostEffectSet::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSObject::Load(rStream,iSaveUse))
		return 0;

	if(!VSResource::Load(rStream,iSaveUse))
		return 0;

	if(!rStream.ReadObjectPtr(m_pPEBeginFunc))
		return 0;
	iSaveUse +=sizeof(VSPostEffectFunction *);

	if(!rStream.ReadObjectPtr(m_pPEEndFunc))
		return 0;
	iSaveUse +=sizeof(VSPostEffectFunction *);

	unsigned int uiPostFunctionNum = 0;
	if(!rStream.Read(&uiPostFunctionNum,sizeof(unsigned int)))
		return 0;
	iSaveUse +=sizeof(unsigned int);

	m_pPostEffectFunctionArray.SetBufferNum(uiPostFunctionNum);

	for (unsigned int i = 0 ; i < uiPostFunctionNum ; i++)
	{
		if(!rStream.ReadObjectPtr(m_pPostEffectFunctionArray[i]))
			return 0;
		iSaveUse +=sizeof(VSPostEffectFunction *);
	}


	return 1;
}

bool VSPostEffectSet::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSPostEffectSet* Temp = DynamicCast<VSPostEffectSet>(pObject); 
	if(!Temp)
		return 0;
	if(VSObject::Clone(pObject,uiType) && VSResource::Clone(Temp,uiType))
	{

		for(unsigned int i = 0 ; i < m_pPostEffectFunctionArray.GetNum() ; i++)
		{
			VSPostEffectFunction * pPostEffectFunction = m_pPostEffectFunctionArray[i];
			m_pPostEffectFunctionArray[i] = NULL;
			VSMAC_DELETE(pPostEffectFunction);
		}
		m_pPostEffectFunctionArray.Clear();

		m_pPEBeginFunc = NULL;
		m_pPEEndFunc = NULL;


		unsigned int uiPostEffectFuntionNum = Temp->m_pPostEffectFunctionArray.GetNum();

		m_pPostEffectFunctionArray.SetBufferNum(uiPostEffectFuntionNum);

		VSPEBeginFunction * pPostBeginFunction = NULL;
		VSPEEndFunction * pPostEndFunction = NULL;
		VSArray<VSPutNode *> OldLinkArray, NewLinkArray;

		for(unsigned int i = 0 ; i < uiPostEffectFuntionNum ;i++)
		{
			VSPostEffectFunction * pTemp1  = Temp->m_pPostEffectFunctionArray[i];
			VSPostEffectFunction * pTemp2 =(VSPostEffectFunction *)VSObject::GetInstance((pTemp1)->GetType().GetName());
			pTemp2->Clone(pTemp1,uiType);
			m_pPostEffectFunctionArray[i] = pTemp2;	
			m_pPostEffectFunctionArray[i]->SetOwner(this);
			pPostBeginFunction = DynamicCast<VSPEBeginFunction>(pTemp2);
			if(pPostBeginFunction)
			{
				m_pPEBeginFunc = pPostBeginFunction;
			}
			pPostEndFunction = DynamicCast<VSPEEndFunction>(pTemp2);
			if(pPostEndFunction)
			{
				m_pPEEndFunc = pPostEndFunction;
			}

			pTemp1->AddAllPutNodeTo(OldLinkArray);
			pTemp2->AddAllPutNodeTo(NewLinkArray);
		}
		for(unsigned int i = 0 ; i < uiPostEffectFuntionNum ;i++)
		{
			if(!m_pPostEffectFunctionArray[i]->Link(OldLinkArray,NewLinkArray))
				return 0;
		}
		VSMAC_ASSERT(m_pPEBeginFunc);
		VSMAC_ASSERT(m_pPEEndFunc);

		return 1;	
	}
	else
		return 0;
}
bool VSPostEffectSet::Register(VSStream & rStream)const
{
	if (rStream.IsObjectRegister(this))
	{
		return 1;
	}
	if(!VSObject::Register(rStream))
		return 0;

	if(!m_pPEBeginFunc->Register(rStream))
		return 0;
	if(!m_pPEEndFunc->Register(rStream))
		return 0;
	for (unsigned int i = 0 ; i < m_pPostEffectFunctionArray.GetNum() ; i++)
	{
		if(!m_pPostEffectFunctionArray[i]->Register(rStream))
			return 0;
	}

	return 1;
}
bool VSPostEffectSet::Link(VSStream & rStream)
{
	if(!VSObject::Link(rStream))
		return 0;
	//m_pShaderMainFunction = (VSShaderMainFunction *)rStream.GetMapValue(GetNextLink());
	rStream.LinkObjectPtr(m_pPEBeginFunc);
	rStream.LinkObjectPtr(m_pPEEndFunc);
	for (unsigned int i = 0 ; i < m_pPostEffectFunctionArray.GetNum() ; i++)
	{
		//m_pShaderFunctionArray[i] = (VSShaderFunction *)rStream.GetMapValue(GetNextLink());
		rStream.LinkObjectPtr(m_pPostEffectFunctionArray[i]);
	}
	return 1;
}
void VSPostEffectSet::Draw(VSCuller & Culler,double dAppTime,
		  VSArray<VSRenderTarget *> * pBeginTargetArray)
{
	m_pPEEndFunc->ClearFlag();
	if(pBeginTargetArray)
	{
		m_pPEBeginFunc->SetPara(pBeginTargetArray);	
	}
	m_pPEEndFunc->Draw(Culler,dAppTime);
}
void VSPostEffectSet::SetBeginTargetArray(VSArray<VSRenderTarget *> * pBeginTargetArray)
{
	m_pPEBeginFunc->SetPara(pBeginTargetArray);
}
void VSPostEffectSet::CheckReCreateRT(unsigned int uiWidth,unsigned int uiHeight)
{
	m_pPEEndFunc->CheckReCreateRT(uiWidth,uiHeight);
}
VSRenderTarget * VSPostEffectSet::GetEndTarget(unsigned int i)
{
	if (i < m_pPEEndFunc->m_pInput.GetNum())
	{
		VSRenderTarget * pTexture = m_pPEEndFunc->GetRenderTarget(m_pPEEndFunc->m_pInput[i]);
		return pTexture;
	}
	return NULL;
}
VSPostEffectFunction * VSPostEffectSet::GetPEFunction(const VSString & Name)
{
	for (unsigned int i = 0 ; i < m_pPostEffectFunctionArray.GetNum() ;i++)
	{
		if (m_pPostEffectFunctionArray[i]->GetShowName() == Name)
		{
			return m_pPostEffectFunctionArray[i];
		}
	}
	return NULL;
}
VSPESetGray::VSPESetGray()
{
	VSPEGray * pPEGray = VS_NEW VSPEGray(_T("Gray"),this);
	m_pPEEndFunc->GetInputNode(VSPEEndFunction::INPUT_COLOR)->Connection(pPEGray->GetOutputNode(VSPEGray::OUT_COLOR));
	pPEGray->GetInputNode(VSPEGray::INPUT_COLOR)->Connection(m_pPEBeginFunc->GetOutputNode(VSPEBeginFunction::OUT_COLOR));
}
VSPESetGray::~VSPESetGray()
{
}
